/* Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.yzbdl.lanius.orchestrate.common.utils;

import java.util.Map;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;
import org.yzbdl.lanius.orchestrate.common.controller.ConfigController;

/**
 * HttpPost 请求工具类
 *
 * @author JCZ
 * @date 2022-04-13 14:27
 */
@Component
public class HttpPostUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpPostUtils.class);

    private RestTemplate restTemplate;

    private SimpleClientHttpRequestFactory requestFactory;

    @Value("${task.config.http_conn_timeout:10000}")
    private Integer connTimeout;

    @Value("${task.config.http_read_timeout:10000}")
    private Integer readTimeout;

    public static HttpPostUtils getInstance() {
        return SpringUtil.getBean("httpPostUtils");
    }

    @PostConstruct
    public void init() {
        requestFactory = new SimpleClientHttpRequestFactory();
        initTimeout();

        ConfigController.reConfigMap.put("http_conn_timeout", (value) -> {
            connTimeout = Integer.valueOf((value));
            initTimeout();
        });
        ConfigController.reConfigMap.put("http_read_timeout", (value) -> {
            readTimeout = Integer.valueOf((value));
            initTimeout();
        });
    }

    /**
     * 发送任务执行请求
     * @param url
     * @param headerMap
     * @param postParameters
     * @return
     */
    public String postWithFormData(String url, Map<String, String> headerMap, MultiValueMap<String, Object> postParameters ) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0");
        httpHeaders.set("Content-Type", "application/x-www-form-urlencoded");
        for (String key : headerMap.keySet()) {
            httpHeaders.set(key, headerMap.get(key));
        }
        HttpEntity httpEntity = new HttpEntity(postParameters, httpHeaders);
        return doRequest(url, httpEntity);
    }

    /**
     * 发送请求
     * @param url
     * @return
     */
    public String post(String url, String auth) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0");
        httpHeaders.set("Content-Type", "text/html");
        httpHeaders.set("Authorization", auth);
        HttpEntity<String> httpEntity = new HttpEntity<>("", httpHeaders);
        return doRequest(url, httpEntity);
    }

    /**
     * 最终请求
     * @param url
     * @param httpEntity
     * @return
     */
    private String doRequest(String url, HttpEntity<String> httpEntity) {
        try{
            return restTemplate.postForObject(url, httpEntity, String.class);
        } catch (HttpServerErrorException e){
            return e.getStatusText();
        } catch (Exception e){
            try {
                return restTemplate.postForObject(url, httpEntity, String.class);
            }catch (Exception e1){
                LOGGER.error("反复调度请求都出现异常："+e1);
                throw e1;
            }
        }
    }


    private void initTimeout() {
        requestFactory.setConnectTimeout(connTimeout);
        requestFactory.setReadTimeout(readTimeout);
        restTemplate = new RestTemplate(requestFactory);
    }

}
